package com.xmmj.common.websocket

import android.os.Build
import com.alibaba.fastjson.JSON
import com.xmmj.baselibrary.base.application.BaseApplication
import com.xmmj.baselibrary.utils.websocket.IWebSocket
import com.xmmj.baselibrary.utils.websocket.SimpleWebSocketCallback
import com.xmmj.baselibrary.utils.websocket.WebSocketManager
import com.xmmj.common.config.AppConfig
import org.java_websocket.handshake.ServerHandshake
import java.util.*

/**
 * 长链接
 */
class WebSocketClient {
    private var mAddress: String = AppConfig.SOCKET
    private var mWebSocket: IWebSocket? = null

    /**
     * 初始化WebSocket
     */
    private fun initWebSocket(address: String) {
        mWebSocket = WebSocketManager.Builder.create()
            .setWebSocketAddress(address) //服务器地址
            .setHeartbeatData(heartbeatBean)
            .setHeartbeatPeriod(HEART_BEAT_PERIOD) //心跳发送间隔(未设置心跳包内容则不发送心跳包)
            .setReconnectPeriod(RECONNECT_PERIOD) //断线重连重试间隔，连接用的是Blocking方法，此处的间隔表示的是一次连接尝试直到回调连接失败后，下次尝试连接的间隔时间
            .setWebSocketEventListener(mWebSocketCallback) //事件回调
            .setVerifyHeartBeat(true) //客户端是否验证心跳包，true的话onReceiverMsg接收消息自行判断是否是心跳包，然后调用refreshHeartFlag()方法刷新心跳标识
            .setDebug(BaseApplication.isDebug) //是否打印日志，默认打印
            .build()
        mWebSocket!!.connect()
        mAddress = address
    }

    /**
     * 获取心跳包数据
     */
    private val heartbeatBean: String
        get() {
            val language: Locale =
                BaseApplication.context.getResources().getConfiguration().locale
            val wsHeartbeatBean = HeartbeatBean()
            wsHeartbeatBean.accessToken = "123456"
            wsHeartbeatBean.device = Build.MODEL
            wsHeartbeatBean.lang = language.language
            wsHeartbeatBean.platform = "Android"
            return JSON.toJSONString(wsHeartbeatBean)
        }

    /**
     * 回调
     */
    private val mWebSocketCallback: SimpleWebSocketCallback = object : SimpleWebSocketCallback() {

        override fun onConnected(handshake: ServerHandshake?) {
            sendMsg(heartbeatBean)
        }

        override fun onDisconnected(code: Int, reason: String?, remote: Boolean) {

        }

        override fun onReceiverMsg(msg: String?) {
            var msgBean: MsgBean? = null
            try {
                msgBean = JSON.parseObject<MsgBean>(msg, MsgBean::class.java)
            } catch (e: Exception) {
                e.printStackTrace()
            }
            if (msgBean == null) {
                return
            }
            handlerMsg(msgBean)
        }
    }

    /**
     * 处理消息
     *
     * @param msg 消息
     */
    private fun handlerMsg(msg: MsgBean) {
        when (msg.type) {
            "beat" -> {
                if (mWebSocket != null) {
                    mWebSocket!!.refreshHeartFlag()
                }
            }
            "battleInvite" -> {
                var battleInvite: BattleInviteBean? = msg.parseData(BattleInviteBean::class.java)
            }
            else -> {

            }
        }
    }

    /**
     * 发送消息
     *
     * @param msg 消息
     */
    fun sendMsg(msg: String?) {
        if (mWebSocket == null) {
            return
        }
        mWebSocket?.sendMsg(msg)
    }

    /**
     * 释放资源
     */
    fun release() {
        if (mWebSocket?.isConnected() == true) {
            mWebSocket?.destory()
        }
        mWebSocket = null
    }

    /**
     * 重置
     */
    fun reset() {
        synchronized(WebSocketClient::class.java) {
            if (mWebSocket != null) {
                mWebSocket?.destory()
                mWebSocket = null
            }
            if (mWebSocket == null) {
                initWebSocket(mAddress)
            }
        }
    }

    companion object {
        var instance: WebSocketClient? = null
            get() {
                synchronized(WebSocketClient::class.java) {
                    if (field == null) {
                        field = WebSocketClient()
                    }
                    return field
                }
            }
            private set

        //心跳间隔周期
        private const val HEART_BEAT_PERIOD: Long = 15000

        //断线重连间隔周期
        private const val RECONNECT_PERIOD: Long = 5000
    }
}